{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "d1f20875-c50d-46df-906b-49ec1d0c6002",
   "metadata": {},
   "source": [
    "# 5.3 使用斜率自动调节步长"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "c90a18b9-d8e8-431c-856c-35f1e4ed05e1",
   "metadata": {},
   "source": [
    "### 1.任务描述\n",
    "\n",
    "假设一元凸函数的方程为$f(x)=x^2+2$，将$\\eta \\frac{\\mathrm{d} f(x)}{\\mathrm{d} x}$作为步长，用迭代法求函数的极小值。"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "8d7baa9c-93a2-42f3-a3c1-231cdb587f2d",
   "metadata": {},
   "source": [
    "### 2.知识准备\n",
    "\n",
    "见教程。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b77a80eb-a596-4410-8b1f-5322e1d141a3",
   "metadata": {},
   "source": [
    "### 3.任务分析\n",
    "\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "de0514a5-6568-421e-afe4-f38d5dc6f93f",
   "metadata": {},
   "source": [
    "对于函数$f(x)=x^2+2$，其导数公式为$\\frac{\\mathrm{d}y}{\\mathrm{d} x}=2x$ "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "435c6090-cfda-4f46-a550-22a368e41e4a",
   "metadata": {},
   "source": [
    "### 4.任务实施\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "ec75eb6c-5da3-467d-a471-ca3b47242dd6",
   "metadata": {},
   "source": [
    "执行代码"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "2ae9da58-e339-4d22-9f8d-ca255711d89e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "第 0 轮: 调节前的x: 3.0000 ,y: 11.0000 ,dy_dx: 6.0000\n",
      "本轮调整后的x为: 1.2000 ,函数值y为: 3.4400\n",
      "第 1 轮: 调节前的x: 1.2000 ,y: 3.4400 ,dy_dx: 2.4000\n",
      "本轮调整后的x为: 0.4800 ,函数值y为: 2.2304\n",
      "第 2 轮: 调节前的x: 0.4800 ,y: 2.2304 ,dy_dx: 0.9600\n",
      "本轮调整后的x为: 0.1920 ,函数值y为: 2.0369\n",
      "第 3 轮: 调节前的x: 0.1920 ,y: 2.0369 ,dy_dx: 0.3840\n",
      "本轮调整后的x为: 0.0768 ,函数值y为: 2.0059\n",
      "第 4 轮: 调节前的x: 0.0768 ,y: 2.0059 ,dy_dx: 0.1536\n",
      "本轮调整后的x为: 0.0307 ,函数值y为: 2.0009\n",
      "第 5 轮: 调节前的x: 0.0307 ,y: 2.0009 ,dy_dx: 0.0614\n",
      "本轮调整后的x为: 0.0123 ,函数值y为: 2.0002\n",
      "第 6 轮: 调节前的x: 0.0123 ,y: 2.0002 ,dy_dx: 0.0246\n",
      "本轮调整后的x为: 0.0049 ,函数值y为: 2.0000\n",
      "第 7 轮: 调节前的x: 0.0049 ,y: 2.0000 ,dy_dx: 0.0098\n",
      "本轮调整后的x为: 0.0020 ,函数值y为: 2.0000\n",
      "第 8 轮: 调节前的x: 0.0020 ,y: 2.0000 ,dy_dx: 0.0039\n",
      "本轮调整后的x为: 0.0008 ,函数值y为: 2.0000\n",
      "第 9 轮: 调节前的x: 0.0008 ,y: 2.0000 ,dy_dx: 0.0016\n",
      "本轮调整后的x为: 0.0003 ,函数值y为: 2.0000\n",
      "第 10 轮: 调节前的x: 0.0003 ,y: 2.0000 ,dy_dx: 0.0006\n",
      "本轮调整后的x为: 0.0001 ,函数值y为: 2.0000\n",
      "第 11 轮: 调节前的x: 0.0001 ,y: 2.0000 ,dy_dx: 0.0003\n",
      "本轮调整后的x为: 0.0001 ,函数值y为: 2.0000\n",
      "第 12 轮: 调节前的x: 0.0001 ,y: 2.0000 ,dy_dx: 0.0001\n",
      "本轮调整后的x为: 0.0000 ,函数值y为: 2.0000\n"
     ]
    }
   ],
   "source": [
    "import tensorflow as tf\n",
    "# x的初始值\n",
    "x=tf.Variable(3.)\n",
    "# 迭代次数\n",
    "iter=13\n",
    "# 学习率\n",
    "lr=0.3\n",
    "for i in range(0,iter):      \n",
    "#     创建tape对象\n",
    "    with tf.GradientTape() as tape:\n",
    "        y=x**2+2        \n",
    "#     计算导数\n",
    "    dy_dx=tape.gradient(y,x)   \n",
    "    print('第',i,'轮:','调节前的x:','%.4f'%x,',y:','%.4f'%y,',dy_dx:','%.4f'%dy_dx)\n",
    "#     更新x\n",
    "    x.assign_sub(lr*dy_dx)\n",
    "#     更新后的函数值y\n",
    "    y=x**2+2    \n",
    "    print('本轮调整后的x为:','%.4f'%x,',函数值y为:','%.4f'%y)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "947bd149-004c-4238-863f-ba125a57b79b",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
